﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using PhotoOfTheDay.Types;
using System.IO;
using System.Threading;
using Microsoft.Win32;

namespace PhotoOfTheDay
{
    public partial class MainForm : Form
    {
        private delegate void UpdateInvoker();

        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            LoadConfig();
            
            //add thread in here
            Global.Worker = new Thread(CheckerThread);
            Global.Worker.Start();

            if (Global.IsAuto)
            {
                WindowState = FormWindowState.Minimized;
                this.Hide();
            }
        }

        private void LoadConfig()
        {
            //Load the home directory
            string PodPATH = Application.ExecutablePath;
            PodPATH = PodPATH.Substring(0, PodPATH.LastIndexOf("\\") + 1);
            Global.ConfigPath = PodPATH + Global.ConfigPath;
            Global.UpdatePath = PodPATH + Global.UpdatePath;
            Global.UserGuidePath = PodPATH + Global.UserGuidePath;
            
            //Update the update checkerURL
            Global.UpdateChackerURL += Global.RetrieveLinkerTimestamp().Ticks;

            if (!File.Exists(Global.ConfigPath))
            {
                //Most probably first run, ask if user would like to run it on startup
                System.Windows.Forms.DialogResult DR = MessageBox.Show("Would you like PoD to update your wallpaper on windows start up?", "Confirm", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question);
                if (DR == System.Windows.Forms.DialogResult.Yes)
                {
                    RunOnStartUp.Checked = true;
                }
            }

            //set archive path
            string mypicture = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyPictures);
            mypicture = Path.Combine(mypicture, "Photo of the Day");
            if (!Directory.Exists(mypicture))
            {
                Directory.CreateDirectory(mypicture);
            }
            Global.WallpaperPath = Path.Combine(mypicture, "Wallpaper.bmp");

            Global.CurrentConfig = Config.Load(Global.ConfigPath);
            Global.CurrentPhoto = Global.CurrentConfig.CurrentPhoto;

            if (Global.CurrentPhoto.PhotoName != "")
            {
                //lets load current photo
                if (File.Exists(Global.WallpaperPath))
                {
                    Global.PhotoFound = true;
                    FileStream str = File.OpenRead(Global.WallpaperPath);
                    Global.CurrentImage = (Bitmap)Bitmap.FromStream(str);
                    str.Close();
                }
            }

            if (Wallpaper.GetWallpaper() != Global.WallpaperPath)
            {
                System.Windows.Forms.DialogResult DR = MessageBox.Show("Your desktop wallpaper is not managed by PoD changer. Do you want to enable Pod changer now?", "Confirm", System.Windows.Forms.MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question);
                if (DR == System.Windows.Forms.DialogResult.Yes)
                {
                    Wallpaper.SetOwner();
                }
            }

            UpdateUI();

            //if not locked, load today's photo of the day
            if (!Global.CurrentConfig.LockOn)
            {
                NavigateTo(Global.EntranceURL, Global.CurrentConfig.ArchieveOn, true);
            }
        }

        private void NavigateToThread(object obj)
        {
            object[] objs = (object[])obj;
            string url = objs[0] as string;
            bool? archive = objs[1] as bool?;
            bool? setWall = objs[2] as bool?;

            UpdateInvoker UIUpdater = new UpdateInvoker(UpdateUI);
            Photo p =Photo.Navigate(url, archive == true ? true : false);
            if (p.PhotoName != "")
            {
                Global.CurrentPhoto = p;
                is_in_progress = false;
                if (setWall == true)
                {
                    Global.CurrentConfig.CurrentPhoto = Global.CurrentPhoto;
                    Wallpaper.Set(Global.CurrentImage, Global.CurrentConfig.Style);
                    Global.CurrentConfig.Save(Global.ConfigPath);
                }
                this.Invoke(UIUpdater);
            }
            else
            {
                is_in_progress = false;
                this.Invoke(new Action(() =>
                {
                    PhotoOfTheDay.SizeMode = PictureBoxSizeMode.Zoom;
                    PhotoOfTheDay.Image = temp_image;
                    MessageBox.Show("Request time out. Looks like there is a problem with the internet connection", "Connection Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }));
            }
        }

        Image temp_image;

        private void InProgress()
        {
            PhotoOfTheDay.BackgroundImageLayout = ImageLayout.Zoom;

            temp_image = PhotoOfTheDay.Image;

            if (temp_image != null)
            {
                Bitmap bmp = new Bitmap(temp_image.Width, temp_image.Height);
                using (Graphics g = Graphics.FromImage(bmp))
                {
                    g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
                    g.DrawImage(temp_image, new Point(0, 0));
                    g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;
                    SolidBrush b = new SolidBrush(Color.FromArgb(100, Color.White));
                    g.FillRectangle(b, 0, 0, temp_image.Width, temp_image.Height);
                }
                PhotoOfTheDay.BackgroundImage = bmp;
            }
            else
            {
                PhotoOfTheDay.BackgroundImage = temp_image;
            }
            PhotoOfTheDay.SizeMode = PictureBoxSizeMode.CenterImage;
            PhotoOfTheDay.Image = Properties.Resources.pb;
        }

        volatile bool is_in_progress = false;

        private void NavigateTo(string url, bool archive, bool setWall = false)
        {
            if (is_in_progress) return;
            is_in_progress = true;

            InProgress();
            Global.Navigator = new Thread(new ParameterizedThreadStart(NavigateToThread));
            Global.Navigator.Start(new object[] { url, archive, setWall });
        }

        private void LoadPhotoOfTheDay_Click(object sender, EventArgs e)
        {
            NavigateTo(Global.EntranceURL, Global.CurrentConfig.ArchieveOn);
        }

        private void SetWallpaper_Click(object sender, EventArgs e)
        {
            Global.CurrentConfig.CurrentPhoto = Global.CurrentPhoto;
            Wallpaper.Set(Global.CurrentImage, Global.CurrentConfig.Style);
            SetLock.Checked = true;
            Global.CurrentConfig.Save(Global.ConfigPath);
        }

        private void PreviousButton_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            NavigateTo(Global.CurrentPhoto.PreviousLink, Global.CurrentConfig.ArchieveOn);
        }

        private void NextButton_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            NavigateTo(Global.CurrentPhoto.NextLink, Global.CurrentConfig.ArchieveOn);
        }

        private void SetLock_CheckedChanged(object sender, EventArgs e)
        {
            if (Global.CurrentConfig.LockOn == SetLock.Checked) return;
            Global.CurrentConfig.LockOn = SetLock.Checked;
            Global.CurrentConfig.Save(Global.ConfigPath);
        }

        private void SetArchive_CheckedChanged(object sender, EventArgs e)
        {
            if (Global.CurrentConfig.ArchieveOn == SetArchive.Checked) return;
            Global.CurrentConfig.ArchieveOn = SetArchive.Checked;
            Global.CurrentConfig.Save(Global.ConfigPath);
        }

        public void UpdateUI()
        {
            //Update name and publish date
            NameOfThePhoto.Text = Global.CurrentPhoto.PhotoName;
            DateTag.Text = Global.CurrentPhoto.photoDate.ToLongDateString();
            
            //update photo found status
            if (Global.PhotoFound)
            {

                if (!Global.IsCopyrighted)
                {
                    PhotoOfTheDay.SizeMode = PictureBoxSizeMode.Zoom;
                    PhotoOfTheDay.Image = Global.CurrentImage;
                    SetWallpaper.Enabled = true;
                    AddToArchive.Enabled = true;
                    addToArchiveToolStripMenuItem.Enabled = true;
                }
                else
                {
                    Bitmap Bmp = new Bitmap(PhotoOfTheDay.Width, PhotoOfTheDay.Height);
                    Graphics g = Graphics.FromImage(Bmp);
                    g.DrawImage(Global.CurrentImage, new Rectangle(new Point(0, 0), PhotoOfTheDay.Size), new Rectangle(new Point(0, 0), Global.CurrentImage.Size), GraphicsUnit.Pixel);

                    SolidBrush brush = new SolidBrush(Color.FromArgb(200, Color.White));
                    g.FillRectangle(brush, new Rectangle(0, Bmp.Height - 50, Bmp.Width, 50));
                    g.DrawRectangle(Pens.Red, new Rectangle(0, Bmp.Height - 50, Bmp.Width-1, 49));
                    
                    g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
                    System.Drawing.Font textFont = new System.Drawing.Font("Arial", 11f);
                    g.DrawString("Copyright protected Image:\nCan not be downloaded or used as wallpaper", textFont, Brushes.Red, new Point(5, Bmp.Height - 43));
                    g.Dispose();

                    PhotoOfTheDay.SizeMode = PictureBoxSizeMode.Zoom;
                    PhotoOfTheDay.Image = Bmp; //draw a photo with copyright notice
                    SetWallpaper.Enabled = false;
                    AddToArchive.Enabled = false;
                    addToArchiveToolStripMenuItem.Enabled = false;
                    NameOfThePhoto.Text = Global.CurrentPhoto.PhotoName + " (Copyright Protected)";
                }
            }
            else
            {
                PhotoOfTheDay.Image = null;
                SetWallpaper.Enabled = false;
                AddToArchive.Enabled = false;
                addToArchiveToolStripMenuItem.Enabled = false;
                NameOfThePhoto.Text = Global.CurrentPhoto.PhotoName + " (IMAGE NOT AVAILABLE)";
            }


            //check if next and previous photo available
            if (Global.CurrentPhoto.NextAvailable) NextButton.Enabled = true; else NextButton.Enabled = false;
            if (Global.CurrentPhoto.PreviousAvailable) PreviousButton.Enabled = true; else PreviousButton.Enabled = false;
            
            //check settings configuration
            SetLock.Checked = Global.CurrentConfig.LockOn;
            SetArchive.Checked = Global.CurrentConfig.ArchieveOn;

            //check if selected as startup
            RunOnStartUp.Checked = IsStartUp();

            //Enable watching in website
            if (Global.CurrentPhoto.PhotoURL == "")
                NALink.Enabled = false;
            else
                NALink.Enabled = true;

            //Show if update available
            if (Global.UpdateAvailable)
            {
                NvLabel.Visible = true;
                NvLink.Visible = true;
            }
            else
            {
                NvLabel.Visible = false;
                NvLink.Visible = false;
            }
        }

        private void AddToArchive_Click(object sender, EventArgs e)
        {
            string pubdate = Global.CurrentPhoto.photoDate.ToMonthName() + " " + Global.CurrentPhoto.photoDate.Day + ", " + Global.CurrentPhoto.photoDate.Year;
            string caption = Global.CurrentPhoto.PhotoName;
            string mypicture = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyPictures);
            mypicture = Path.Combine(mypicture, "Photo of the Day");
            if (!Directory.Exists(mypicture))
            {
                Directory.CreateDirectory(mypicture);
            }
            mypicture = Path.Combine(mypicture, pubdate + " - " + caption + ".bmp");
            if (File.Exists(mypicture)) { AddToArchive.Enabled = false; return; }
            if (Global.PhotoFound)
            {
                Global.CurrentImage.Save(mypicture, System.Drawing.Imaging.ImageFormat.Bmp);
                AddToArchive.Enabled = false;
                addToArchiveToolStripMenuItem.Enabled = false;
            }
        }

        private void NotificationIcon_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                this.Show();
                this.WindowState = FormWindowState.Normal;
                this.BringToFront();
            }
            else if (e.Button == System.Windows.Forms.MouseButtons.Right)
            {
                Point p = System.Windows.Forms.Cursor.Position;
                p.Y = p.Y - NotificationIcon.ContextMenuStrip.Height;
                NotificationIcon.ContextMenuStrip.Show(p);
            }
        }

        protected override void  OnFormClosing(FormClosingEventArgs e)
        {
            if (e.CloseReason == CloseReason.UserClosing)
            {
                e.Cancel = true;
                WindowState = FormWindowState.Minimized;
                this.Hide();
            }
 	        base.OnFormClosing(e);
        }

        protected override void OnResize(EventArgs e)
        {
            if (WindowState == FormWindowState.Minimized)
            {
                this.Hide();
            }
            base.OnResize(e);
        }

        private void OpenButton_Click(object sender, EventArgs e)
        {
            this.Show();
            this.WindowState = FormWindowState.Normal;
            this.BringToFront();
        }

        private void ExitButton_Click(object sender, EventArgs e)
        {
            System.Windows.Forms.DialogResult DR = MessageBox.Show("Do you really want to terminate PoD tracker?", "Confirm", System.Windows.Forms.MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            if (DR == System.Windows.Forms.DialogResult.Yes)
            {
                ExitApp();
            }
        }

        private void CheckerThread()
        {
            UpdateInvoker UIUpdater = new UpdateInvoker(UpdateUI);
            UpdateInvoker Updater = new UpdateInvoker(UpdateSoftware);

            //lets check for update
            string CheckResponse = Global.GetHTTPData(Global.UpdateChackerURL);
            string[] splited = CheckResponse.Split('|');
            if (splited.Length == 3)
            {
                Global.UpdateAvailable = bool.Parse(splited[0]);
                Global.UpdateURL = splited[2];
                bool IsHigh = bool.Parse(splited[1]);

                if (Global.UpdateAvailable) //If update available, download it
                    Global.UpdateAvailable = Global.DownloadFile(Global.UpdateURL, Global.UpdatePath);

                if (Global.UpdateAvailable)
                {
                    if (IsHigh)
                    {
                        this.Invoke(Updater);
                        return;
                    }
                    else
                    {
                        this.Invoke(UIUpdater);
                    }
                }
            }

            while (true)
            {
                Photo newPhoto = Photo.Navigate(Global.EntranceURL, Global.CurrentConfig.ArchieveOn);
                Global.CurrentConfig.LastChecked = DateTime.Now;
                if (!Global.CurrentConfig.LockOn)
                {
                    if (newPhoto.photoDate != Global.CurrentConfig.CurrentPhoto.photoDate)
                    {
                        //lets set the wallpaper
                        Global.CurrentConfig.CurrentPhoto = newPhoto;
                        Wallpaper.Set(Global.CurrentImage, Global.CurrentConfig.Style);
                        Global.CurrentConfig.Save(Global.ConfigPath);
                    }
                }
                Thread.Sleep(900000);//check in every 15 minutes
            }
        }

        private void LoadCurrent_Click(object sender, EventArgs e)
        {
            Global.CurrentPhoto = Global.CurrentConfig.CurrentPhoto;
            //lets load current photo
            if (File.Exists(Global.WallpaperPath))
            {
                Global.PhotoFound = true;
                FileStream str = File.OpenRead(Global.WallpaperPath);
                Global.CurrentImage = (Bitmap)Bitmap.FromStream(str);
                str.Close();
            }
            else
            {
                Global.PhotoFound = false;
                Global.CurrentImage = null;
            }
            UpdateUI();
        }

        private void NALink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (Global.CurrentPhoto.PhotoURL != "")
                System.Diagnostics.Process.Start(Global.CurrentPhoto.PhotoURL);
        }

        private void OpenArchive_Click(object sender, EventArgs e)
        {
            string mypicture = System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyPictures);
            mypicture = Path.Combine(mypicture, "Photo of the Day");
            if (!Directory.Exists(mypicture))
            {
                Directory.CreateDirectory(mypicture);
            }
            System.Diagnostics.Process.Start(mypicture);
        }

        private void RunOnStartUp_CheckedChanged(object sender, EventArgs e)
        {
            if (RunOnStartUp.Checked == IsStartUp()) return;
            RegistryKey StartUp = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true);

            if (RunOnStartUp.Checked)
            {
                StartUp.SetValue("PhotoOfTheDay", GetStartUpPath());
            }
            else
            {
                StartUp.DeleteValue("PhotoOfTheDay");
            }

            StartUp.Close();
        }

        private bool IsStartUp()
        {
            bool toReturn = false;
            //check if runing on startup
            RegistryKey StartUp = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run", false);
            try
            {
                string currentPath = StartUp.GetValue("PhotoOfTheDay").ToString();
                string myPath = GetStartUpPath();
                if (currentPath.ToLower() == myPath.ToLower())
                {
                    toReturn = true;
                }
                else
                {
                    toReturn = false;
                }
            }
            catch
            {
                toReturn = false;
            }
            StartUp.Close();
            return toReturn;
        }

        private string GetStartUpPath()
        {
            return Application.ExecutablePath + " /MINIMIZED";
        }

        private void exitToTrayToolStripMenuItem_Click(object sender, EventArgs e)
        {
            WindowState = FormWindowState.Minimized;
            this.Hide();
        }

        private void donateToolStripMenuItem_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start(Global.DonationURL);
        }

        /// <summary>
        /// if update found, use this to update to newer version
        /// </summary>
        private void UpdateSoftware()
        {
            if (File.Exists(Global.UpdatePath))
            {
                System.Diagnostics.Process.Start(Global.UpdatePath, "/install");
                ExitApp();
            }
        }

        private void ExitApp()
        {
            if (Global.Worker != null && Global.Worker.IsAlive)
            {
                Global.Worker.Abort();
            }
            if (Global.PhotoArchiver != null && Global.PhotoArchiver.IsAlive)
            {
                Global.PhotoArchiver.Abort();
            }
            if (Global.Navigator != null && Global.Navigator.IsAlive)
            {
                Global.Navigator.Abort();
            }
            NotificationIcon.Dispose();
            Application.Exit();
        }

        private void NvLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            UpdateSoftware();
        }

        private void advancedArchivingOptionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (Global.archiver == null) Global.archiver = new Archiver();
            Global.archiver.Show();
            Global.archiver.BringToFront();
        }

        private void checkForUpdatesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            new AboutPodChanger().ShowDialog(this);
        }

        private void userGuideToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (!File.Exists(Global.UserGuidePath))
            {
                Global.DownloadFile(Global.UserGuideURL, Global.UserGuidePath);
            }
            System.Diagnostics.Process.Start(Global.UserGuidePath);
        }

        private void OnuprovaLink_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start(Global.OnuprovaPage);
        }

        private void FacebookLink_Click(object sender, EventArgs e)
        {
            System.Diagnostics.Process.Start(Global.FacebookPage);
        }

        private void customizeWallpaperToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (CustomizeWallpaper customizer = new CustomizeWallpaper())
            {
                customizer.ShowDialog(this);
            }
        }
    }
}
